home *** CD-ROM | disk | FTP | other *** search
- //////////
- //
- // File: QTGraphImp.c
- //
- // Contains: Sample code for using QuickTime's graphics import routines.
- //
- // Written by: Tim Monroe
- // Based loosely on the SimpleGIExample.c code written by Apple DTS;
- // exporting code based heavily on Dispatch 14 from the Ice Floe by Sam Bushell.
- //
- // Copyright: © 1998 by Apple Computer, Inc., all rights reserved.
- //
- // Change History (most recent first):
- //
- // <2> 06/02/98 rtm added QTGraphImp_ExportGWorldToFile and _GetAvailableExportTypes,
- // from Dispatch 14 from the Ice Floe; added QTGraphImp_ExportImageFile
- // <1> 04/14/98 rtm first file
- //
- // This sample code illustrates how to use QuickTime's graphics importer routines
- // to open and display image files. The graphics importer routines were introduced
- // in QuickTime version 2.5 as a new way to draw still images. The graphics import
- // routines (for example, GetGraphicsImporterForFile) use graphics import components
- // (of component type 'grip') to open and perform other operations on image files.
- // Essentially, you can use the graphics import routines to insulate your application
- // from the nitty gritty details of the image file format and compression used in the
- // image.
- //
- // This code also shows how to export images as picture files, and how to determine which
- // formats an image can be exported in. The QT functions that support these operations
- // were introduced in QuickTime version 3.
- //
- // In this sample code, we allow the user to open an image file; then we draw it into
- // a window on the screen. Your application, of course, will probably want to do more
- // interesting things with the image. We also allow the user to save an image using JPEG
- // compression.
- //
- //////////
-
- // header files
- #include "QTGraphImp.h"
-
- // global variables
- WindowPtr gImageWindow = NULL; // the window we display the image in
- GraphicsImportComponent gImporter = NULL;
-
-
- //////////
- //
- // QTGraphImp_PromptUserForImageFileAndDisplay
- // Let the user select an image file, then display it in a window.
- //
- //////////
-
- void QTGraphImp_PromptUserForImageFileAndDisplay (void)
- {
- SFTypeList myTypeList;
- StandardFileReply myReply;
- Rect myRect;
- OSErr myErr = noErr;
-
- // have the user select an image file;
- // kQTFileTypeQuickTimeImage means any image file readable by GetGraphicsImporterForFile
- myTypeList[0] = kQTFileTypeQuickTimeImage;
-
- StandardGetFilePreview(NULL, 1, myTypeList, &myReply);
- if (!myReply.sfGood)
- goto bail;
-
- //////////
- //
- // get a graphics importer for the image file and determine the natural size of the image
- //
- //////////
-
- myErr = GetGraphicsImporterForFile(&myReply.sfFile, &gImporter);
- if (myErr != noErr)
- goto bail;
-
- myErr = GraphicsImportGetNaturalBounds(gImporter, &myRect);
- if (myErr != noErr)
- goto bail;
-
- //////////
- //
- // create a window to display the image in; then draw into that window
- //
- //////////
-
- MacOffsetRect(&myRect, 50, 50);
- gImageWindow = NewCWindow(NULL, &myRect, myReply.sfFile.name, true, movableDBoxProc, (WindowPtr)-1L, true, 0);
- if (gImageWindow == NULL)
- goto bail;
-
- // set the current port and draw
- GraphicsImportSetGWorld(gImporter, (CGrafPtr)gImageWindow, NULL);
- GraphicsImportDraw(gImporter);
-
- bail:
- if (myErr != noErr)
- if (gImporter != NULL)
- CloseComponent(gImporter);
- }
-
-
- //////////
- //
- // QTGraphImp_PromptUserForDiskFileAndSaveCompressed
- // Let the user select a disk file, then compress the current picture into that file.
- //
- //////////
-
- void QTGraphImp_PromptUserForDiskFileAndSaveCompressed (void)
- {
- StandardFileReply myReply;
- Rect myRect;
- GWorldPtr myGWorld;
- StringPtr myImagePrompt = QTUtils_ConvertCToPascalString(kSaveImagePrompt);
- StringPtr myImageFileName = QTUtils_ConvertCToPascalString(kSaveImageFileName);
- OSErr myErr = noErr;
-
- // have the user select the name of the new image file
- StandardPutFile(myImagePrompt, myImageFileName, &myReply);
- if (!myReply.sfGood)
- goto bail;
-
- // get the natural size of the image
- myErr = GraphicsImportGetNaturalBounds(gImporter, &myRect);
- if (myErr != noErr)
- goto bail;
-
- // create an offscreen graphics world to draw the image into
- myErr = NewGWorld(&myGWorld, 0, &myRect, NULL, NULL, 0);
- if (myErr == noErr) {
- GraphicsImportSetGWorld(gImporter, (CGrafPtr)myGWorld, NULL);
- GraphicsImportDraw(gImporter);
-
- // save the compressed image
- QTGraphImp_SaveCompressedImage(myGWorld, &myReply.sfFile);
- if (myGWorld != NULL)
- DisposeGWorld(myGWorld);
- }
-
- bail:
- free(myImagePrompt);
- free(myImageFileName);
- }
-
-
- //////////
- //
- // QTGraphImp_SaveCompressedImage
- // Save the current image as a compressed file.
- //
- //////////
-
- void QTGraphImp_SaveCompressedImage (GWorldPtr theWorld, FSSpec *theFile)
- {
- ImageDescriptionHandle myDesc;
- Handle myData;
- Rect myRect;
- PixMapHandle myPixMap;
- CTabHandle myCTab = NULL;
- ICMFlushProcRecord myFlushProc;
- short myRefNum;
- short myDepth;
- OSErr myErr = noErr;
-
- if ((theWorld == NULL) || (theFile == NULL))
- goto bail;
-
- myDesc = (ImageDescriptionHandle)NewHandle(sizeof(ImageDescription));
- if (myDesc == NULL)
- goto bail;
-
- myRect = theWorld->portRect;
- myPixMap = GetGWorldPixMap(theWorld);
-
- if (LockPixels(myPixMap)) {
-
- // if less than 16-bit, then get the color table of our GWorld
- myDepth = (**myPixMap).pixelSize;
- if (myDepth < 16)
- myCTab = (**myPixMap).pmTable;
-
- myData = NewHandle(kBufferSize);
- myErr = MemError();
-
- if ((myData != NULL) && (myErr == noErr)) {
- CodecType myCodec = kJPEGCodecType;
-
- HLock(myData);
-
- myErr = FSpCreate(theFile, kImageFileCreator, kQTFileTypeJPEG, 0);
-
- if (myErr == noErr)
- myErr = FSpOpenDF(theFile, fsRdWrPerm, &myRefNum);
-
- if (myErr == noErr)
- myErr = SetFPos(myRefNum, fsFromStart, 0);
-
- if (myErr == noErr) {
- ICMFlushProcRecordPtr myFlushProcPtr = NULL;
-
- #if USE_FLUSH_PROC
- myFlushProc.flushProc = NewICMFlushProc(QTGraphImp_DataUnloadProc);
- myFlushProc.flushRefCon = myRefNum;
- myFlushProcPtr = &myFlushProc;
- #else
- myFlushProcPtr = NULL;
- #endif
- // compress the image
- myErr = FCompressImage( myPixMap,
- &myRect,
- myDepth,
- codecNormalQuality,
- myCodec,
- anyCodec,
- myCTab,
- codecFlagWasCompressed,
- kBufferSize,
- myFlushProcPtr,
- NULL,
- myDesc,
- *myData);
-
- #if !USE_FLUSH_PROC
- if (myErr == noErr)
- myErr = FSWrite(myRefNum, &(**myDesc).dataSize, *myData);
- #endif
-
- if (myErr == noErr)
- myErr = SetFPos(myRefNum, fsFromStart, (**myDesc).dataSize);
-
- if (myErr == noErr)
- myErr = SetEOF(myRefNum, (**myDesc).dataSize);
-
- if (myErr == noErr)
- myErr = FSClose(myRefNum);
-
- HUnlock(myData);
- DisposeHandle(myData);
-
- #if USE_FLUSH_PROC
- DisposeRoutineDescriptor(myFlushProc.flushProc);
- #endif
- }
- }
- }
-
- UnlockPixels(myPixMap);
-
- bail:
- if (myDesc != NULL)
- DisposeHandle((Handle)myDesc);
- }
-
-
- //////////
- //
- // QTGraphImp_DataUnloadProc
- // A data unloading procedure: write the compressed data to disk.
- //
- // The theRefCon parameter is assumed to be a file reference number of an open file.
- //
- //////////
-
- PASCAL_RTN OSErr QTGraphImp_DataUnloadProc (Ptr theData, long theBytesNeeded, long theRefCon)
- {
- OSErr myErr = noErr;
-
- if (theData == NULL) {
- // if data is NULL, set a new position in the file from the current mark, offset by bytesNeeded
- myErr = SetFPos(theRefCon, fsFromMark, theBytesNeeded);
- } else {
- // otherwise, write the specified data to disk
- myErr = FSWrite(theRefCon, &theBytesNeeded, theData);
- }
-
- return(myErr);
- }
-
-
- //////////
- //
- // QTGraphImp_ExportGWorldToFile
- // Save the image in a graphics world to the specified file.
- //
- // Use this function when you've got an image that you want to export to a file
- // but that image wasn't read in from a file (in which case you could just use
- // the GetGraphicsImporterForFile function to open an appropriate graphics importer).
- //
- // Based on the function ExportGWorldToFile in Dispatch 14 from the Ice Floe.
- //
- //////////
-
- OSErr QTGraphImp_ExportGWorldToFile (GWorldPtr theWorld, FSSpec *theFile, OSType theType)
- {
- PicHandle myPicture = NULL;
- GraphicsImportComponent myImporter = NULL;
- Handle myHandle = NULL;
- CGrafPtr mySavedGW;
- GDHandle mySavedGD;
- OSErr myErr = noErr;
-
- // save the current graphics world, and set the specified graphics world as current
- GetGWorld(&mySavedGW, &mySavedGD);
- SetGWorld(theWorld, NULL);
-
- // capture the contents of the specified graphics world in a picture handle
- myPicture = OpenPicture(&((GrafPtr)theWorld)->portRect);
- CopyBits( &((GrafPtr)theWorld)->portBits,
- &((GrafPtr)theWorld)->portBits,
- &((GrafPtr)theWorld)->portRect,
- &((GrafPtr)theWorld)->portRect,
- srcCopy,
- NULL);
-
- ClosePicture();
-
- // convert the picture handle into a handle-based PICT file by adding a 512-byte header to the start;
- // picture files are just like picture handles, except that they have an extra 512-byte header at the
- // front; any data in this header is usually ignored but it must exist, for historical reasons
- myHandle = NewHandleClear(512);
- myErr = MemError();
- if (myErr != noErr)
- goto bail;
-
- myErr = HandAndHand((Handle)myPicture, myHandle);
- if (myErr != noErr)
- goto bail;
-
- // open an instance of the picture file graphics importer
- myErr = OpenADefaultComponent(GraphicsImporterComponentType, kQTFileTypePicture, &myImporter);
- if (myErr != noErr)
- goto bail;
-
- myErr = GraphicsImportSetDataHandle(myImporter, myHandle);
- if (myErr != noErr)
- goto bail;
-
- // export the image to a file
- myErr = GraphicsImportExportImageFile(myImporter, theType, kImageFileCreator, theFile, smSystemScript);
-
- bail:
- // restore the original graphics world
- SetGWorld(mySavedGW, mySavedGD);
-
- if (myPicture != NULL)
- KillPicture(myPicture);
-
- if (myImporter != NULL)
- CloseComponent(myImporter);
-
- if (myHandle != NULL)
- DisposeHandle(myHandle);
-
- return(myErr);
- }
-
-
- //////////
- //
- // QTGraphImp_GetAvailableExportTypes
- // Get a list of the available image export file types.
- //
- // Based on a function in Dispatch 14 from the Ice Floe.
- //
- //////////
-
- OSErr QTGraphImp_GetAvailableExportTypes (GraphicsImportComponent theImporter)
- {
- QTAtomContainer myContainer = NULL;
- short myCount, myIndex;
- OSErr myErr = noErr;
-
- // get an atom container that contains one or more kGraphicsExportGroup atoms;
- // each export group atom represents a single export format and has child atoms that indicate
- // the file type (kGraphicsExportFileType), a human-readable name (kGraphicsExportDescription),
- // a file extension (kGraphicsExportExtension) and a MIME type (kGraphicsExportMIMEType)
- myErr = GraphicsImportGetExportImageTypeList(theImporter, &myContainer);
- if (myErr != noErr)
- goto bail;
-
- myCount = QTCountChildrenOfType(myContainer, kParentAtomIsContainer, kGraphicsExportGroup);
- for (myIndex = 1; myIndex <= myCount; myIndex++) {
- QTAtom myGroupAtom;
-
- myGroupAtom = QTFindChildByIndex(myContainer, kParentAtomIsContainer, kGraphicsExportGroup, myIndex, NULL);
- if (myGroupAtom != 0) {
- QTAtom myTypeAtom;
-
- myTypeAtom = QTFindChildByIndex(myContainer, myGroupAtom, kGraphicsExportFileType, 1, NULL);
- if (myTypeAtom != 0) {
- OSType myType;
-
- myErr = QTCopyAtomDataToPtr(myContainer, myTypeAtom, false, sizeof(myType), &myType, NULL);
- // the data in QT atoms is always big-endian, so convert the file type to native format
- myType = EndianU32_BtoN(myType);
-
- // at this point, you probably want to do something interesting with the file type, eh?
- // this is left as an exercise for the reader
-
- } else {
- myErr = cannotFindAtomErr;
- }
- }
- }
-
- bail:
- if (myContainer != NULL)
- QTDisposeAtomContainer(myContainer);
- return(myErr);
- }
-
-
- //////////
- //
- // QTGraphImp_ExportImageFile
- // Let the user select a disk file, then export the current picture into that file.
- //
- //////////
-
- OSErr QTGraphImp_ExportImageFile (GraphicsImportComponent theImporter)
- {
- OSType myType;
- FSSpec myFSSpec;
- OSErr myErr = noErr;
-
- myErr = GraphicsImportDoExportImageFileDialog(
- theImporter,
- NULL, // no default name for the file
- NULL, // use the default prompt in the dialog box
- NULL, // no modal dialog filter procedure
- &myType, // return the type of the selected file
- &myFSSpec, // return the name (etc.) of the selected file
- NULL); // don't return the script code
- return(myErr);
- }